<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;

class AccessLog
{

    /** @var int unknown error length */
    protected $unknownLength = 8192;

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        // 非生产或调试模式，记录全局请求日志
        if (!isProd() || isDebug()) {
            $loadData = [
                'method' => strtoupper($request->method()),
                'route' => $request->getUri(),
                'code' => response('code')->getStatusCode(),
                'params' => $request->all(),
                'token' => $request->cookie('token') ? : $request->header('token'),
                'referer' => $request->header('referer'),
                'ip' => getRealIp(),
            ];
            // 添加响应
            $loadData['response'] = $this->getContent($response);
            $json = json_encode($loadData, JSON_UNESCAPED_SLASHES);
            Log::channel('access')->info($json . PHP_EOL);
        }
        return $response;
    }

    /**
     * get response content
     * @param $response
     * @return array|mixed
     */
    public function getContent($response)
    {
        if ($response instanceof JsonResponse) {
            $content = json_decode($response->getContent(), true);
        } elseif ($response instanceof  Response) {
            $errorCode = $response->getStatusCode();
            $errorInfo = json_decode($response->getContent(), true);
            if ($errorInfo && isset($errorInfo['statusCode'])) {
                $content = $errorInfo;
            } else {
                $content = [
                    'message' => $response->exception ? $response->exception->getMessage() : 'xxx',
                    'statusCode' => $errorCode,
                    'success' => false,
                    'result' => $this->getUnknownError($response->getContent()),
                ];
            }
        } else {
            $content = [
                'message' => 'UNKNOWN ERROR',
                'statusCode' => 99999,
                'success' => false,
                'result' => $this->getUnknownError(json_encode($response)),
            ];
        }
        return $content;
    }

    /**
     * get unknown error
     * @param $errorMsg
     * @return false|string
     */
    private function getUnknownError($errorMsg)
    {
        return substr(str_replace([PHP_EOL, '  '], ['^M', ' '], $errorMsg), 0, $this->unknownLength);
    }

}
